home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 5 / Skunkware 5.iso / src / X11 / xantfarm / xantfarm.c < prev    next >
C/C++ Source or Header  |  1995-06-20  |  34KB  |  1,238 lines

  1. /* xantfarm - Insect world - build it up, tear it down.
  2. **
  3. ** Copyright (C) 1991 by Jef Poskanzer
  4. **
  5. ** Permission to use, copy, modify, and distribute this software and its
  6. ** documentation for any purpose and without fee is hereby granted, provided
  7. ** that the above copyright notice appear in all copies and that both that
  8. ** copyright notice and this permission notice appear in supporting
  9. ** documentation.  This software is provided "as is" without express or
  10. ** implied warranty.
  11. */
  12.  
  13. #ifndef lint
  14. static char rcsid[] =
  15.     "@(#) $Header: xantfarm.c,v 1.8 91/10/16 21:39:24 jef Exp $";
  16. #endif
  17.  
  18. #include <stdio.h>
  19. #include <sys/types.h>
  20. #include <sys/ioctl.h>
  21. #include <sys/time.h>
  22.  
  23. #include <X11/X.h>
  24. #include <X11/Xlib.h>
  25. #include <X11/Xutil.h>
  26. #include <X11/Xatom.h>
  27.  
  28. /* Add fd_set definitions, in case the system doesn't have them. */
  29. #ifndef FD_SET
  30. #define NFDBITS     32
  31. #define FD_SETSIZE  32
  32. #define FD_SET(n, p)    ((p)->fds_bits[(n)/NFDBITS] |= (1 << ((n) % NFDBITS)))
  33. #define FD_CLR(n, p)    ((p)->fds_bits[(n)/NFDBITS] &= ~(1 << ((n) % NFDBITS)))
  34. #define FD_ISSET(n, p)  ((p)->fds_bits[(n)/NFDBITS] & (1 << ((n) % NFDBITS)))
  35. #define FD_ZERO(p)  bzero((char *)(p), sizeof(*(p)))
  36. #endif
  37.  
  38. /* Sand bitmap. */
  39. #define sand_width 4
  40. #define sand_height 4
  41. static char sand_bits[] = {0x0a,0x05,0x0a,0x05};
  42.  
  43. /* Ant bitmaps. */
  44. #define ant_ld0_width 12
  45. #define ant_ld0_height 4
  46. static char ant_ld0_bits[] = {0x03,0x00,0xec,0x07,0xff,0x07,0x20,0x09};
  47. #define ant_ld1_width 12
  48. #define ant_ld1_height 4
  49. static char ant_ld1_bits[] = {0x03,0x00,0xec,0x07,0xff,0x07,0x90,0x04};
  50. #define ant_lu0_width 12
  51. #define ant_lu0_height 4
  52. static char ant_lu0_bits[] = {0x20,0x09,0xff,0x07,0xec,0x07,0x03,0x00};
  53. #define ant_lu1_width 12
  54. #define ant_lu1_height 4
  55. static char ant_lu1_bits[] = {0x90,0x04,0xff,0x07,0xec,0x07,0x03,0x00};
  56. #define ant_rd0_width 12
  57. #define ant_rd0_height 4
  58. static char ant_rd0_bits[] = {0x00,0x0c,0x7e,0x03,0xfe,0x0f,0x49,0x00};
  59. #define ant_rd1_width 12
  60. #define ant_rd1_height 4
  61. static char ant_rd1_bits[] = {0x00,0x0c,0x7e,0x03,0xfe,0x0f,0x92,0x00};
  62. #define ant_ru0_width 12
  63. #define ant_ru0_height 4
  64. static char ant_ru0_bits[] = {0x49,0x00,0xfe,0x0f,0x7e,0x03,0x00,0x0c};
  65. #define ant_ru1_width 12
  66. #define ant_ru1_height 4
  67. static char ant_ru1_bits[] = {0x92,0x00,0xfe,0x0f,0x7e,0x03,0x00,0x0c};
  68. #define ant_ur0_width 4
  69. #define ant_ur0_height 12
  70. static char ant_ur0_bits[] = {
  71.     0x05,0x05,0x06,0x06,0x04,0x0e,0x06,0x06,0x0e,0x06,0x06,0x08};
  72. #define ant_ur1_width 4
  73. #define ant_ur1_height 12
  74. static char ant_ur1_bits[] = {
  75.     0x05,0x05,0x06,0x06,0x0c,0x06,0x06,0x0e,0x06,0x06,0x0e,0x00};
  76. #define ant_ul0_width 4
  77. #define ant_ul0_height 12
  78. static char ant_ul0_bits[] = {
  79.     0x0a,0x0a,0x06,0x06,0x02,0x07,0x06,0x06,0x07,0x06,0x06,0x01};
  80. #define ant_ul1_width 4
  81. #define ant_ul1_height 12
  82. static char ant_ul1_bits[] = {
  83.     0x0a,0x0a,0x06,0x06,0x03,0x06,0x06,0x07,0x06,0x06,0x07,0x00};
  84. #define ant_dr0_width 4
  85. #define ant_dr0_height 12
  86. static char ant_dr0_bits[] = {
  87.     0x08,0x06,0x06,0x0e,0x06,0x06,0x0e,0x04,0x06,0x06,0x05,0x05};
  88. #define ant_dr1_width 4
  89. #define ant_dr1_height 12
  90. static char ant_dr1_bits[] = {
  91.     0x00,0x0e,0x06,0x06,0x0e,0x06,0x06,0x0c,0x06,0x06,0x05,0x05};
  92. #define ant_dl0_width 4
  93. #define ant_dl0_height 12
  94. static char ant_dl0_bits[] = {
  95.     0x01,0x06,0x06,0x07,0x06,0x06,0x07,0x02,0x06,0x06,0x0a,0x0a};
  96. #define ant_dl1_width 4
  97. #define ant_dl1_height 12
  98. static char ant_dl1_bits[] = {
  99.     0x00,0x07,0x06,0x06,0x07,0x06,0x06,0x03,0x06,0x06,0x0a,0x0a};
  100. #define antc_ld0_width 12
  101. #define antc_ld0_height 4
  102. static char antc_ld0_bits[] = {0x03,0x00,0xed,0x07,0xff,0x07,0x20,0x09};
  103. #define antc_ld1_width 12
  104. #define antc_ld1_height 4
  105. static char antc_ld1_bits[] = {0x03,0x00,0xed,0x07,0xff,0x07,0x90,0x04};
  106. #define antc_lu0_width 12
  107. #define antc_lu0_height 4
  108. static char antc_lu0_bits[] = {0x20,0x09,0xff,0x07,0xed,0x07,0x03,0x00};
  109. #define antc_lu1_width 12
  110. #define antc_lu1_height 4
  111. static char antc_lu1_bits[] = {0x90,0x04,0xff,0x07,0xed,0x07,0x03,0x00};
  112. #define antc_rd0_width 12
  113. #define antc_rd0_height 4
  114. static char antc_rd0_bits[] = {0x00,0x0c,0x7e,0x0b,0xfe,0x0f,0x49,0x00};
  115. #define antc_rd1_width 12
  116. #define antc_rd1_height 4
  117. static char antc_rd1_bits[] = {0x00,0x0c,0x7e,0x0b,0xfe,0x0f,0x92,0x00};
  118. #define antc_ru0_width 12
  119. #define antc_ru0_height 4
  120. static char antc_ru0_bits[] = {0x49,0x00,0xfe,0x0f,0x7e,0x0b,0x00,0x0c};
  121. #define antc_ru1_width 12
  122. #define antc_ru1_height 4
  123. static char antc_ru1_bits[] = {0x92,0x00,0xfe,0x0f,0x7e,0x0b,0x00,0x0c};
  124. #define antc_ur0_width 4
  125. #define antc_ur0_height 12
  126. static char antc_ur0_bits[] = {
  127.     0x07,0x05,0x06,0x06,0x04,0x0e,0x06,0x06,0x0e,0x06,0x06,0x08};
  128. #define antc_ur1_width 4
  129. #define antc_ur1_height 12
  130. static char antc_ur1_bits[] = {
  131.     0x07,0x05,0x06,0x06,0x0c,0x06,0x06,0x0e,0x06,0x06,0x0e,0x00};
  132. #define antc_ul0_width 4
  133. #define antc_ul0_height 12
  134. static char antc_ul0_bits[] = {
  135.     0x0e,0x0a,0x06,0x06,0x02,0x07,0x06,0x06,0x07,0x06,0x06,0x01};
  136. #define antc_ul1_width 4
  137. #define antc_ul1_height 12
  138. static char antc_ul1_bits[] = {
  139.     0x0e,0x0a,0x06,0x06,0x03,0x06,0x06,0x07,0x06,0x06,0x07,0x00};
  140. #define antc_dr0_width 4
  141. #define antc_dr0_height 12
  142. static char antc_dr0_bits[] = {
  143.     0x08,0x06,0x06,0x0e,0x06,0x06,0x0e,0x04,0x06,0x06,0x05,0x07};
  144. #define antc_dr1_width 4
  145. #define antc_dr1_height 12
  146. static char antc_dr1_bits[] = {
  147.     0x00,0x0e,0x06,0x06,0x0e,0x06,0x06,0x0c,0x06,0x06,0x05,0x07};
  148. #define antc_dl0_width 4
  149. #define antc_dl0_height 12
  150. static char antc_dl0_bits[] = {
  151.     0x01,0x06,0x06,0x07,0x06,0x06,0x07,0x02,0x06,0x06,0x0a,0x0e};
  152. #define antc_dl1_width 4
  153. #define antc_dl1_height 12
  154. static char antc_dl1_bits[] = {
  155.     0x00,0x07,0x06,0x06,0x07,0x06,0x06,0x03,0x06,0x06,0x0a,0x0e};
  156.  
  157.  
  158. /* Definitions. */
  159.  
  160. #define RANDOM_DIG_PROB 200     /* dig down while wandering */
  161. #define RANDOM_DROP_PROB 200        /* drop while wandering */
  162. #define RANDOM_TURN_PROB 200        /* turn while wandering */
  163. #define CONCAVE_BELOW_DIG_PROB 10   /* dig a concave corner below ground*/
  164. #define CONVEX_ABOVE_DROP_PROB 10   /* drop at convex corner above ground */
  165. #define CALM_PROB 100           /* calm down from a panic */
  166.  
  167. #define COMPACT 15      /* this depth of sand turns to dirt */
  168. #define DIRT_START_FRAC 0.666666
  169.  
  170. #define GRID_SIZE sand_width
  171. #define ANT_GRIDS ( ant_lu0_width / GRID_SIZE )
  172.  
  173. /* The three elements. */
  174. #define E_AIR 0
  175. #define E_DIRT 1
  176. #define E_SAND 2
  177.  
  178. typedef struct ant_struct {
  179.     int x, y;
  180.     int dir;
  181.     int behavior;
  182.     int timer;
  183.     int phase;
  184.     } ant;
  185.  
  186. /* The eight directions. */
  187. #define D_LEFT_DOWN 0
  188. #define D_LEFT_UP 1
  189. #define D_RIGHT_DOWN 2
  190. #define D_RIGHT_UP 3
  191. #define D_UP_RIGHT 4
  192. #define D_UP_LEFT 5
  193. #define D_DOWN_RIGHT 6
  194. #define D_DOWN_LEFT 7
  195. #define N_DIRS 8
  196. #define N_ALTPIXMAPS 2
  197.  
  198. /* The three behaviors. */
  199. #define B_WANDERING 0
  200. #define B_CARRYING 1
  201. #define B_PANIC 2
  202.  
  203. /* Timing factors for the three behaviors. */
  204. #define T_WANDERING 4
  205. #define T_CARRYING 5
  206. #define T_PANIC 1
  207.  
  208. typedef struct falling_sand_struct {
  209.     int x, y;
  210.     int active;
  211.     } falling_sand;
  212.  
  213.  
  214.  
  215. /* Externals. */
  216.  
  217. extern char* malloc();
  218. extern char* realloc();
  219. extern long time();
  220. extern long random();
  221.  
  222.  
  223. /* Forward routines. */
  224.  
  225. static void x_init();
  226. static Window VirtualRootWindowOfScreen();
  227. static void ant_init();
  228. static void main_loop();
  229. static void expose();
  230. static void paint_run();
  231. static void poke();
  232. static void invalidate();
  233. static void invalidate_ant();
  234. static void cleanup();
  235.  
  236. static void moveants();
  237. static void move();
  238. static void turn();
  239. static int legal_dir();
  240. static int try_dig();
  241. static void loosen_neighbors();
  242. static void loosen_one();
  243. static void drop();
  244. static void behave();
  245. static void sand_fall();
  246.  
  247.  
  248. /* Variables. */
  249.  
  250. static char* argv0;
  251.  
  252. static Display* display;
  253. static Screen* screen;
  254. static Window root;
  255. static int root_w, root_h, root_d;
  256. static unsigned long foreground, background;
  257. static GC airgc;
  258. static GC sandgc;
  259. static Pixmap sand_pixmap;
  260. static GC antgc;
  261. static char* ant_bits[N_DIRS][N_ALTPIXMAPS] = {
  262.     ant_ld0_bits, ant_ld1_bits, ant_lu0_bits, ant_lu1_bits,
  263.     ant_rd0_bits, ant_rd1_bits, ant_ru0_bits, ant_ru1_bits,
  264.     ant_ur0_bits, ant_ur1_bits, ant_ul0_bits, ant_ul1_bits,
  265.     ant_dr0_bits, ant_dr1_bits, ant_dl0_bits, ant_dl1_bits };
  266. static char* antc_bits[N_DIRS][N_ALTPIXMAPS] = {
  267.     antc_ld0_bits, antc_ld1_bits, antc_lu0_bits, antc_lu1_bits,
  268.     antc_rd0_bits, antc_rd1_bits, antc_ru0_bits, antc_ru1_bits,
  269.     antc_ur0_bits, antc_ur1_bits, antc_ul0_bits, antc_ul1_bits,
  270.     antc_dr0_bits, antc_dr1_bits, antc_dl0_bits, antc_dl1_bits };
  271. static int ant_width[N_DIRS] = {
  272.     ant_ld0_width, ant_lu0_width, ant_rd0_width, ant_ru0_width,
  273.     ant_ur0_width, ant_ul0_width, ant_dr0_width, ant_dl0_width };
  274. static int ant_height[N_DIRS] = {
  275.     ant_ld0_height, ant_lu0_height, ant_rd0_height, ant_ru0_height,
  276.     ant_ur0_height, ant_ul0_height, ant_dr0_height, ant_dl0_height };
  277. static Pixmap ant_pixmap[N_DIRS][N_ALTPIXMAPS];
  278. static Pixmap antc_pixmap[N_DIRS][N_ALTPIXMAPS];
  279. static int num_exposerects, max_exposerects;
  280. static XRectangle* exposerects;
  281.  
  282. static int cycles;
  283. static int world_w, world_h;
  284. static int surface;
  285. static unsigned char** world;
  286. static ant* ants;
  287. static int num_ants;
  288. static int dx[N_DIRS] = { -1, -1, 1, 1, 0, 0, 0, 0 };
  289. static int dy[N_DIRS] = { 0, 0, 0, 0, -1, -1, 1, 1 };
  290. static int foot_dir[N_DIRS] = {
  291.     D_DOWN_RIGHT, D_UP_RIGHT, D_DOWN_LEFT, D_UP_LEFT,
  292.     D_RIGHT_DOWN, D_LEFT_DOWN, D_RIGHT_UP, D_LEFT_UP };
  293. static int back_dir[N_DIRS] = {
  294.     D_UP_LEFT, D_DOWN_LEFT, D_UP_RIGHT, D_DOWN_RIGHT,
  295.     D_LEFT_UP, D_RIGHT_UP, D_LEFT_DOWN, D_RIGHT_DOWN };
  296. #define D_LEFT_DOWN 0
  297. #define D_LEFT_UP 1
  298. #define D_RIGHT_DOWN 2
  299. #define D_RIGHT_UP 3
  300. #define D_UP_RIGHT 4
  301. #define D_UP_LEFT 5
  302. #define D_DOWN_RIGHT 6
  303. #define D_DOWN_LEFT 7
  304. static int num_falling_sands, max_falling_sands;
  305. static falling_sand* falling_sands;
  306.  
  307.  
  308. /* Routines. */
  309.  
  310. void
  311. main( argc, argv )
  312.     int argc;
  313.     char* argv[];
  314.     {
  315.     int printpid;
  316.     char* display_name;
  317.     int synchronous;
  318.     int pid, tty;
  319.  
  320.     /* Parse args. */
  321.     argv0 = argv[0];
  322.     num_ants = 10;
  323.     cycles = 15;
  324.     printpid = 0;
  325.     display_name = (char*) 0;
  326.     synchronous = 0;
  327.     for( ; ; )
  328.     {
  329.     if ( argc >= 3 && strcmp( argv[1], "-n" ) == 0 )
  330.         {
  331.         ++argv; --argc;
  332.         num_ants = atoi( argv[1] );
  333.         if ( num_ants <= 0 )
  334.         goto usage;
  335.         ++argv; --argc;
  336.         continue;
  337.         }
  338.     if ( argc >= 3 && strcmp( argv[1], "-c" ) == 0 )
  339.         {
  340.         ++argv; --argc;
  341.         cycles = atoi( argv[1] );
  342.         if ( cycles < 0 )
  343.         goto usage;
  344.         ++argv; --argc;
  345.         continue;
  346.         }
  347.     if ( argc >= 2 && strcmp( argv[1], "-i" ) == 0 )
  348.         {
  349.         ++argv; --argc;
  350.         printpid = 1;
  351.         continue;
  352.         }
  353.     if ( argc >= 3 && (
  354.            strcmp( argv[1], "-display" ) == 0 ||
  355.            strcmp( argv[1], "-displa" ) == 0 ||
  356.            strcmp( argv[1], "-displ" ) == 0 ||
  357.            strcmp( argv[1], "-disp" ) == 0 ||
  358.            strcmp( argv[1], "-dis" ) == 0 ||
  359.            strcmp( argv[1], "-di" ) == 0 ||
  360.            strcmp( argv[1], "-d" ) == 0 ) )
  361.         {
  362.         ++argv; --argc;
  363.         display_name = argv[1];
  364.         ++argv; --argc;
  365.         continue;
  366.         }
  367.     if ( argc >= 2 && (
  368.            strcmp( argv[1], "-sync" ) == 0 ||
  369.            strcmp( argv[1], "-syn" ) == 0 ||
  370.            strcmp( argv[1], "-sy" ) == 0 ||
  371.            strcmp( argv[1], "-s" ) == 0 ) )
  372.         {
  373.         ++argv; --argc;
  374.         synchronous = 1;
  375.         continue;
  376.         }
  377.     break;
  378.     }
  379.  
  380.     if ( argc > 1 )
  381.     {
  382. usage:
  383.     (void) fprintf(
  384.         stderr, "usage: %s [-n num] [-c cycles] [-i] [-display name]\n", argv0 );
  385.     exit( 1 );
  386.     }
  387.  
  388.     /* Initialize the random number generator. */
  389.     srandom( (int) ( time( (long*) 0 ) ^ getpid() ) );
  390.  
  391.     /* Set up X stuff. */
  392.     x_init( display_name, synchronous );
  393.  
  394.     /* Create the ant world. */
  395.     ant_init();
  396.  
  397.     /* Fork, if necessary. */
  398.     if ( printpid )
  399.     {
  400.     pid = fork();
  401.     if ( pid < 0 )
  402.         {
  403.         perror( "fork" );
  404.         exit( 1 );
  405.         }
  406.     else if ( pid > 0 )
  407.         {
  408.         /* Parent just exits. */
  409.         exit( 0 );
  410.         }
  411.     (void) printf( "%d\n", getpid() );
  412.     (void) fflush( stdout );
  413.  
  414.     /* Go stealth (ditch our controlling tty). */
  415.     tty = open( "/dev/tty", 0 );
  416.     if ( tty < 0 )
  417.         {
  418.         (void) fprintf( stderr, "%s: ", argv0 );
  419.         perror( "/dev/tty open" );
  420.         exit( 1 );
  421.         }
  422. #if 0
  423.     else
  424.         {
  425.         if ( ioctl( tty, TIOCNOTTY, 0 ) < 0 )
  426.         {
  427.         (void) fprintf( stderr, "%s: ", argv0 );
  428.         perror( "TIOCNOTTY ioctl" );
  429.         exit( 1 );
  430.         }
  431.         (void) close( tty );
  432.         }
  433. #endif
  434.     }
  435.  
  436.     /* Main loop. */
  437.     main_loop();
  438.  
  439.     /*NOTREACHED*/
  440.     }
  441.  
  442. static void
  443. x_init( display_name, synchronous )
  444.     char* display_name;
  445.     int synchronous;
  446.     {
  447.     int i, j;
  448.  
  449.     display = XOpenDisplay( display_name );
  450.     if ( display == (Display*) 0 )
  451.     {
  452.     (void) fprintf(
  453.         stderr, "%s: can't open display \"%s\"\n", argv0,
  454.         XDisplayName( display_name ) );
  455.     exit( 1 );
  456.     }
  457.     if ( synchronous )
  458.     XSynchronize( display, 1 );
  459.     screen = DefaultScreenOfDisplay( display );
  460.     root = VirtualRootWindowOfScreen( screen );
  461.     root_w = WidthOfScreen( screen );
  462.     root_h = HeightOfScreen( screen );
  463.     root_d = DefaultDepthOfScreen( screen );
  464.     foreground = BlackPixelOfScreen( screen );
  465.     background = WhitePixelOfScreen( screen );
  466.     /* Air is all white, so its GC should paint white. */
  467.     airgc = XCreateGC( display, root, 0, (XGCValues*) 0 );
  468.     XSetForeground( display, airgc, background );
  469.     XSetBackground( display, airgc, foreground );
  470.     /* Sand is a pixmap, so its GC tiles. */
  471.     sandgc = XCreateGC( display, root, 0, (XGCValues*) 0 );
  472.     XSetForeground( display, sandgc, foreground );
  473.     XSetBackground( display, sandgc, background );
  474.     XSetFillStyle( display, sandgc, FillTiled );
  475.     sand_pixmap = XCreatePixmapFromBitmapData(
  476.     display, root, sand_bits, sand_width, sand_height,
  477.     foreground, background, root_d );
  478.     XSetTile( display, sandgc, sand_pixmap );
  479.     /* Ants paint black through a clipping bitmap. */
  480.     antgc = XCreateGC( display, root, 0, (XGCValues*) 0 );
  481.     XSetForeground( display, antgc, foreground );
  482.     XSetBackground( display, antgc, background );
  483.     for ( i = 0; i < N_DIRS; ++i )
  484.     for ( j = 0; j < N_ALTPIXMAPS; ++j )
  485.         {
  486.         ant_pixmap[i][j] = XCreateBitmapFromData(
  487.         display, root, ant_bits[i][j], ant_width[i], ant_height[i] );
  488.         antc_pixmap[i][j] = XCreateBitmapFromData(
  489.         display, root, antc_bits[i][j], ant_width[i], ant_height[i] );
  490.         }
  491.     num_exposerects = max_exposerects = 0;
  492.     }
  493.  
  494. /* From vroot.h by Andreas Stolcke. */
  495. static Window
  496. VirtualRootWindowOfScreen( screen )
  497.     Screen* screen;
  498.     {
  499.     static Screen* save_screen = (Screen*) 0;
  500.     static Window root = (Window) 0;
  501.  
  502.     if ( screen != save_screen )
  503.     {
  504.     Display* dpy = DisplayOfScreen( screen );
  505.     Atom __SWM_VROOT = None;
  506.     int i;
  507.     Window rootReturn, parentReturn;
  508.     Window* children;
  509.     unsigned int numChildren;
  510.  
  511.     root = RootWindowOfScreen( screen );
  512.  
  513.     /* Go look for a virtual root. */
  514.     __SWM_VROOT = XInternAtom( dpy, "__SWM_VROOT", False );
  515.     if ( XQueryTree(
  516.          dpy, root, &rootReturn, &parentReturn, &children,
  517.          &numChildren ) )
  518.         {
  519.         for ( i = 0; i < numChildren; ++i)
  520.         {
  521.         Atom actual_type;
  522.         int actual_format;
  523.         unsigned long nitems, bytesafter;
  524.         Window* newRoot = (Window*) 0;
  525.  
  526.         if ( XGetWindowProperty(
  527.              dpy, children[i], __SWM_VROOT, 0, 1, False, XA_WINDOW,
  528.              &actual_type, &actual_format, &nitems, &bytesafter,
  529.              (unsigned char**) &newRoot ) == Success && newRoot )
  530.             {
  531.             root = *newRoot;
  532.             break;
  533.             }
  534.         }
  535.         if ( children )
  536.         XFree( (char*) children );
  537.         }
  538.  
  539.     save_screen = screen;
  540.     }
  541.  
  542.     return root;
  543.     }
  544.  
  545. static void
  546. ant_init()
  547.     {
  548.     int x, y, a;
  549.  
  550.     world_w = root_w / GRID_SIZE;
  551.     world_h = root_h / GRID_SIZE;
  552.     world = (unsigned char**) malloc(
  553.     (unsigned) ( world_h * sizeof(unsigned char*) ) );
  554.     if ( world == (unsigned char**) 0 )
  555.     {
  556.     (void) fprintf( stderr, "%s: out of memory\n", argv0 );
  557.     exit( 1 );
  558.     }
  559.     for ( y = 0; y < world_h; ++y )
  560.     {
  561.     world[y] = (unsigned char*) malloc(
  562.         (unsigned) ( world_w * sizeof(unsigned char) ) );
  563.     if ( world[y] == (unsigned char*) 0 )
  564.         {
  565.         (void) fprintf( stderr, "%s: out of memory\n", argv0 );
  566.         exit( 1 );
  567.         }
  568.     }
  569.     surface = world_h * ( 1.0 - DIRT_START_FRAC );
  570.     for ( y = 0; y < surface; ++y )
  571.     for ( x = 0; x < world_w; ++x )
  572.         world[y][x] = E_AIR;
  573.     for ( ; y < world_h; ++y )
  574.     for ( x = 0; x < world_w; ++x )
  575.         world[y][x] = E_DIRT;
  576.     ants = (ant*) malloc( (unsigned) ( num_ants * sizeof(ant) ) );
  577.     if ( ants == (ant*) 0 )
  578.     {
  579.     (void) fprintf( stderr, "%s: out of memory\n", argv0 );
  580.     exit( 1 );
  581.     }
  582.     for ( a = 0; a < num_ants; ++a )
  583.     {
  584.     ants[a].x = random() % world_w;
  585.     ants[a].y = surface - 1;
  586.     ants[a].dir = random() % 2 == 1 ? D_LEFT_DOWN : D_RIGHT_DOWN;
  587.     behave( a, B_WANDERING, T_WANDERING );
  588.     ants[a].phase = 0;
  589.     }
  590.     num_falling_sands = max_falling_sands = 0;
  591.     }
  592.  
  593. static void
  594. main_loop()
  595.     {
  596.     int fd, i;
  597.     fd_set fds;
  598.     struct timeval timeout;
  599.     XEvent ev;
  600.  
  601.     XSelectInput( display, root, ExposureMask | PointerMotionMask );
  602.     invalidate( 0, 0, world_w, world_h );
  603.     FD_ZERO( &fds );
  604.     fd = ConnectionNumber( display );
  605.     for (;;)
  606.     {
  607.     if ( num_exposerects != 0 )
  608.         {
  609.         for ( i = 0; i < num_exposerects; ++i )
  610.         expose(
  611.             exposerects[i].x, exposerects[i].y,
  612.             (int) exposerects[i].width, (int) exposerects[i].height );
  613.         num_exposerects = 0;
  614.         continue;
  615.         }
  616.     if ( cycles != 0 && XPending( display ) == 0 )
  617.         {
  618.         /* No X events to handle, so wait for a while. */
  619.         FD_SET( fd, &fds );
  620.         timeout.tv_sec = 1 / cycles;
  621.         timeout.tv_usec = 1000000L / cycles;
  622.         (void) select( fd + 1, &fds, (int*) 0, (int*) 0, &timeout );
  623.         }
  624.     if ( XPending( display ) == 0 )
  625.         {
  626.         /* Still no X events, so let's move. */
  627.         moveants();
  628.         if ( num_falling_sands > 0 )
  629.         sand_fall();
  630.         continue;
  631.         }
  632.     /* Now there are X events. */
  633.     XNextEvent( display, &ev );
  634.     switch ( ev.type )
  635.         {
  636.         case Expose:
  637.         expose(
  638.         ev.xexpose.x, ev.xexpose.y,
  639.         ev.xexpose.width, ev.xexpose.height );
  640.         break;
  641.  
  642.         case MotionNotify:
  643.         poke( ev.xmotion.x, ev.xmotion.y );
  644.         break;
  645.         }
  646.     }
  647.     }
  648.  
  649. static void
  650. expose( ex, ey, ew, eh )
  651.     int ex, ey, ew, eh;
  652.     {
  653.     int x0, y0, x1, y1, x, y, a, d, ax, ay;
  654.     int run_start, run_count, run_type;
  655.  
  656.     /* Convert to ant world coordinates. */
  657.     x0 = ex / GRID_SIZE;
  658.     if ( x0 < 0 ) x0 = 0;
  659.     y0 = ey / GRID_SIZE;
  660.     if ( y0 < 0 ) y0 = 0;
  661.     x1 = ( ex + ew - 1 ) / GRID_SIZE;
  662.     if ( x1 >= world_w ) x1 = world_w - 1;
  663.     y1 = ( ey + eh - 1 ) / GRID_SIZE;
  664.     if ( y1 >= world_h ) y1 = world_h - 1;
  665.  
  666.     /* Paint the ant world. */
  667.     for ( y = y0; y <= y1; ++y )
  668.     {
  669.     /* Collect up a run of identical elements, so we can paint them
  670.     ** all at once and save oodles of cycles.
  671.     */
  672.     run_start = x0;
  673.     run_count = 1;
  674.     run_type = world[y][x0];
  675.     for ( x = x0 + 1; x <= x1; ++x )
  676.         {
  677.         if ( world[y][x] == run_type )
  678.         ++run_count;
  679.         else
  680.         {
  681.         paint_run( run_start, run_count, run_type, y );
  682.         run_start = x;
  683.         run_count = 1;
  684.         run_type = world[y][x];
  685.         }
  686.         }
  687.     if ( run_count > 0 )
  688.         paint_run( run_start, run_count, run_type, y );
  689.     }
  690.  
  691.     /* Now paint any ants in the exposed area. */
  692.     for ( a = 0; a < num_ants; ++a )
  693.     {
  694.     if ( ants[a].x + ANT_GRIDS / 2 >= x0 &&
  695.          ants[a].x - ANT_GRIDS / 2 <= x1 &&
  696.          ants[a].y + ANT_GRIDS / 2 >= y0 &&
  697.          ants[a].y - ANT_GRIDS / 2 <= y1 )
  698.         {
  699.         d = ants[a].dir;
  700.         ax = ants[a].x * GRID_SIZE - ant_width[d] / 2 + GRID_SIZE / 2;
  701.         ay = ants[a].y * GRID_SIZE - ant_height[d] / 2 + GRID_SIZE / 2;
  702.         if ( ants[a].behavior == B_CARRYING )
  703.         XSetClipMask( display, antgc, antc_pixmap[d][ants[a].phase] );
  704.         else
  705.         XSetClipMask( display, antgc, ant_pixmap[d][ants[a].phase] );
  706.         XSetClipOrigin( display, antgc, ax, ay );
  707.         XFillRectangle(
  708.         display, root, antgc, ax, ay, ant_width[d], ant_height[d] );
  709.         }
  710.     }
  711.     }
  712.  
  713. static void
  714. paint_run( run_start, run_count, run_type, y )
  715.     int run_start, run_count, run_type, y;
  716.     {
  717.     switch ( run_type )
  718.     {
  719.     case E_AIR:
  720.     XFillRectangle(
  721.         display, root, airgc, run_start * GRID_SIZE, y * GRID_SIZE,
  722.         run_count * GRID_SIZE, GRID_SIZE );
  723.     break;
  724.  
  725.     case E_DIRT:
  726.     /* Dirt shows as the default root pattern. */
  727.     XClearArea(
  728.         display, root, run_start * GRID_SIZE, y * GRID_SIZE,
  729.         run_count * GRID_SIZE, GRID_SIZE, False );
  730.     break;
  731.  
  732.     case E_SAND:
  733.     XFillRectangle(
  734.         display, root, sandgc, run_start * GRID_SIZE, y * GRID_SIZE,
  735.         run_count * GRID_SIZE, GRID_SIZE );
  736.     break;
  737.     }
  738.     }
  739.  
  740. static void
  741. poke( px, py )
  742.     int px, py;
  743.     {
  744.     int x, y, a, nx, ny;
  745.  
  746.     x = px / GRID_SIZE;
  747.     y = py / GRID_SIZE;
  748.     for ( a = 0; a < num_ants; ++a )
  749.     {
  750.     if ( x >= ants[a].x - ANT_GRIDS / 2 && x <= ants[a].x + ANT_GRIDS / 2 &&
  751.          y >= ants[a].y - ANT_GRIDS / 2 && y <= ants[a].y + ANT_GRIDS / 2 )
  752.         {
  753.         if ( ants[a].behavior == B_CARRYING )
  754.         drop( a );
  755.         nx = ants[a].x + random() % 3 - 1;
  756.         ny = ants[a].y + random() % 3 - 1;
  757.         if ( nx < 0 ) nx = 0;
  758.         if ( ny < 0 ) ny = 0;
  759.         if ( nx >= world_w ) nx = world_w - 1;
  760.         if ( ny >= world_h ) ny = world_h - 1;
  761.         invalidate_ant( a );
  762.         ants[a].x = nx;
  763.         ants[a].y = ny;
  764.         ants[a].dir = random() % N_DIRS;
  765.         invalidate_ant( a );
  766.         behave( a, B_PANIC, T_PANIC );
  767.         }
  768.     }
  769.     }
  770.  
  771. static void
  772. invalidate( x, y, w, h )
  773.     int x, y, w, h;
  774.     {
  775.     int i, ex, ey, ew, eh;;
  776.  
  777.     x *= GRID_SIZE;
  778.     y *= GRID_SIZE;
  779.     w *= GRID_SIZE;
  780.     h *= GRID_SIZE;
  781.  
  782.     /* Check if this rectangle intersects an existing one. */
  783.     for ( i = 0; i < num_exposerects; ++i )
  784.     {
  785.     ex = exposerects[i].x;
  786.     ey = exposerects[i].y;
  787.     ew = exposerects[i].width;
  788.     eh = exposerects[i].height;
  789.     if ( x < ex + ew && ex < x + w && y < ey + eh && ey < y + h )
  790.         {
  791.         /* Found an intersection - merge them. */
  792.         if ( x + w > ex + ew )
  793.         exposerects[i].width = ew = x + w - ex;
  794.         if ( y + h > ey + eh )
  795.         exposerects[i].height = eh = y + h - ey;
  796.         if ( x < ex )
  797.         {
  798.         exposerects[i].width = ex + ew - x;
  799.         exposerects[i].x = x;
  800.         }
  801.         if ( y < ey )
  802.         {
  803.         exposerects[i].height = ey + eh - y;
  804.         exposerects[i].y = y;
  805.         }
  806.         return;
  807.         }
  808.     }
  809.  
  810.     /* Nope, add a new XRectangle. */
  811.     if ( num_exposerects == max_exposerects )
  812.     {
  813.     if ( max_exposerects == 0 )
  814.         {
  815.         max_exposerects = 20;
  816.         exposerects = (XRectangle*) malloc(
  817.         (unsigned) ( max_exposerects * sizeof(XRectangle) ) );
  818.         }
  819.     else
  820.         {
  821.         max_exposerects *= 2;
  822.         exposerects = (XRectangle*) realloc(
  823.         (char*) exposerects,
  824.         (unsigned) ( max_exposerects * sizeof(XRectangle) ) );
  825.         }
  826.     if ( exposerects == (XRectangle*) 0 )
  827.         {
  828.         (void) fprintf( stderr, "%s: out of memory\n", argv0 );
  829.         exit( 1 );
  830.         }
  831.     }
  832.     exposerects[num_exposerects].x = x;
  833.     exposerects[num_exposerects].y = y;
  834.     exposerects[num_exposerects].width = w;
  835.     exposerects[num_exposerects].height = h;
  836.     ++num_exposerects;
  837.     }
  838.  
  839. static void
  840. invalidate_ant( a )
  841.     int a;
  842.     {
  843.     invalidate(
  844.     ants[a].x - ANT_GRIDS / 2, ants[a].y - ANT_GRIDS / 2,
  845.     ANT_GRIDS, ANT_GRIDS );
  846.     }
  847.  
  848. static void
  849. cleanup()
  850.     {
  851.     int i, j;
  852.  
  853.     XFreePixmap( display, sand_pixmap );
  854.     for ( i = 0; i < N_DIRS; ++i )
  855.     for ( j = 0; j < N_ALTPIXMAPS; ++j )
  856.         {
  857.         XFreePixmap( display, ant_pixmap[i][j] );
  858.         XFreePixmap( display, antc_pixmap[i][j] );
  859.         }
  860.     XFreeGC( display, airgc );
  861.     XFreeGC( display, sandgc );
  862.     XFreeGC( display, antgc );
  863.     XCloseDisplay( display );
  864.     }
  865.  
  866. static void
  867. moveants()
  868.     {
  869.     int a, x, y, fx, fy;
  870.  
  871.     for ( a = 0; a < num_ants; ++a )
  872.     {
  873.     --ants[a].timer;
  874.     if ( ants[a].timer <= 0 )
  875.         {
  876.         ants[a].phase = ( ants[a].phase + 1 ) % N_ALTPIXMAPS;
  877.  
  878.         /* Gravity check. */
  879.         x = ants[a].x;
  880.         y = ants[a].y;
  881.         fx = x + dx[foot_dir[ants[a].dir]];
  882.         fy = y + dy[foot_dir[ants[a].dir]];
  883.         if ( fx >= 0 && fx < world_w && fy >= 0 && fy < world_h &&
  884.          world[fy][fx] == E_AIR )
  885.         {
  886.         /* Whoops, whatever we were walking on disappeared. */
  887.         if ( y + 1 < world_h && world[y + 1][x] == E_AIR )
  888.             {
  889.             invalidate_ant( a );
  890.             ants[a].y = y + 1;
  891.             invalidate_ant( a );
  892.             }
  893.         else
  894.             /* Can't fall?  Try turning. */
  895.             turn( a );
  896.         }
  897.         else
  898.         {
  899.         /* Ok, the ant gets to do something. */
  900.         switch ( ants[a].behavior )
  901.             {
  902.             case B_WANDERING:
  903.             if ( random() % RANDOM_DIG_PROB == 0 )
  904.             (void) try_dig( a, 0 );
  905.             else if ( random() % RANDOM_TURN_PROB == 0 )
  906.             turn( a );
  907.             else
  908.             {
  909.             behave( a, B_WANDERING, T_WANDERING );
  910.             move( a );
  911.             }
  912.             break;
  913.  
  914.             case B_CARRYING:
  915.             if ( random() % RANDOM_DROP_PROB == 0 )
  916.             drop( a );
  917.             else
  918.             {
  919.             behave( a, B_CARRYING, T_CARRYING );
  920.             move( a );
  921.             }
  922.             break;
  923.  
  924.             case B_PANIC:
  925.             if ( random() % CALM_PROB == 0 )
  926.             {
  927.             behave( a, B_WANDERING, T_WANDERING );
  928.             }
  929.             else
  930.             {
  931.             behave( a, B_PANIC, T_PANIC );
  932.             move( a );
  933.             }
  934.             break;
  935.             }
  936.         }
  937.         }
  938.     }
  939.     }
  940.  
  941. static void
  942. move( a )
  943.     int a;
  944.     {
  945.     int x, y, i, d, nx, ny, fx, fy;
  946.  
  947.     x = ants[a].x;
  948.     y = ants[a].y;
  949.     d = ants[a].dir;
  950.     nx = x + dx[d];
  951.     ny = y + dy[d];
  952.  
  953.     if ( nx < 0 || nx >= world_w || ny < 0 || ny >= world_h )
  954.     {
  955.     /* Hit an edge.  Turn. */
  956.     turn( a );
  957.     return;
  958.     }
  959.  
  960.     if ( world[ny][nx] != E_AIR )
  961.     {
  962.     /* Hit dirt or sand.  Dig? */
  963.     if ( ants[a].behavior == B_WANDERING && ants[a].y >= surface &&
  964.          random() % CONCAVE_BELOW_DIG_PROB == 0 )
  965.         /* Yes, try digging. */
  966.         (void) try_dig( a, 1 );
  967.     else
  968.         /* Nope, no digging.  Turn. */
  969.         turn( a );
  970.     return;
  971.     }
  972.  
  973.     /* We can move forward.  But first, check footing. */
  974.     fx = nx + dx[foot_dir[d]];
  975.     fy = ny + dy[foot_dir[d]];
  976.     if ( fx >= 0 && fx < world_w && fy >= 0 && fy < world_h &&
  977.      world[fy][fx] == E_AIR )
  978.     {
  979.     /* Whoops, we're over air.  Move into the air and turn towards
  980.     ** the feet.  But first, see if we should drop.
  981.     */
  982.     if ( ants[a].behavior == B_CARRYING && ants[a].y < surface &&
  983.          random() % CONVEX_ABOVE_DROP_PROB == 0 )
  984.         drop( a );
  985.     nx = fx;
  986.     ny = fy;
  987.     ants[a].dir = foot_dir[d];
  988.     }
  989.  
  990.     /* Ok. */
  991.     invalidate_ant( a );
  992.     ants[a].x = nx;
  993.     ants[a].y = ny;
  994.     invalidate_ant( a );
  995.     }
  996.  
  997. static void
  998. turn( a )
  999.     int a;
  1000.     {
  1001.     int n, d;
  1002.     int ok_dirs[N_DIRS];
  1003.  
  1004.     /* First check if turning "up" is ok. */
  1005.     d = back_dir[ants[a].dir];
  1006.     if ( legal_dir( a, d ) )
  1007.     ants[a].dir = d;
  1008.     else
  1009.     {
  1010.     /* Make a list of the legal directions. */
  1011.     n = 0;
  1012.     for ( d = 0; d < N_DIRS; ++d )
  1013.         {
  1014.         if ( d != ants[a].dir && legal_dir( a, d ) )
  1015.         {
  1016.         ok_dirs[n] = d;
  1017.         ++n;
  1018.         }
  1019.         }
  1020.     
  1021.     if ( n != 0 )
  1022.         {
  1023.         /* Choose a random legal direction. */
  1024.         ants[a].dir = ok_dirs[random() % n];
  1025.         }
  1026.     else
  1027.         {
  1028.         /* No legal directions to turn?  Trapped!  If we're carrying,
  1029.         ** drop, then turn randomly.  Perhaps we can dig ourselves out.
  1030.         */
  1031.         if ( ants[a].behavior == B_CARRYING )
  1032.         drop( a );
  1033.         ants[a].dir = random() % N_DIRS;
  1034.         }
  1035.     }
  1036.     invalidate_ant( a );
  1037.     }
  1038.  
  1039. static int
  1040. legal_dir( a, d )
  1041.     int a, d;
  1042.     {
  1043.     int nx, ny;
  1044.  
  1045.     /* Check that there's air ahead. */
  1046.     nx = ants[a].x + dx[d];
  1047.     ny = ants[a].y + dy[d];
  1048.     if ( nx < 0 || nx >= world_w || ny < 0 || ny >= world_h ||
  1049.      world[ny][nx] != E_AIR )
  1050.     return 0;
  1051.  
  1052.     /* Check that there's solid footing. */
  1053.     nx = ants[a].x + dx[foot_dir[d]];
  1054.     ny = ants[a].y + dy[foot_dir[d]];
  1055.     if ( nx >= 0 && nx < world_w && ny >= 0 && ny < world_h &&
  1056.      world[ny][nx] == E_AIR )
  1057.     return 0;
  1058.  
  1059.     return 1;
  1060.     }
  1061.  
  1062. static int
  1063. try_dig( a, forward )
  1064.     int a, forward;
  1065.     {
  1066.     int x, y;
  1067.  
  1068.     if ( forward )
  1069.     {
  1070.     x = ants[a].x + dx[ants[a].dir];
  1071.     y = ants[a].y + dy[ants[a].dir];
  1072.     }
  1073.     else
  1074.     {
  1075.     x = ants[a].x + dx[foot_dir[ants[a].dir]];
  1076.     y = ants[a].y + dy[foot_dir[ants[a].dir]];
  1077.     }
  1078.  
  1079.     if ( x >= 0 && x < world_w && y >= 0 && y < world_h &&
  1080.      world[y][x] != E_AIR )
  1081.     {
  1082.     world[y][x] = E_AIR;
  1083.     invalidate( x, y, 1, 1 );
  1084.     loosen_neighbors( x, y );
  1085.     behave( a, B_CARRYING, T_CARRYING );
  1086.     return 1;
  1087.     }
  1088.     else
  1089.     return 0;
  1090.     }
  1091.  
  1092. static void
  1093. loosen_neighbors( xc, yc )
  1094.     int xc, yc;
  1095.     {
  1096.     int x, y;
  1097.  
  1098.     for ( y = yc + 1; y >= yc - 1; --y )
  1099.     for ( x = xc - 1; x <= xc + 1; ++x )
  1100.         if ( x >= 0 && x < world_w && y >= 0 && y < world_h &&
  1101.          world[y][x] == E_SAND )
  1102.         loosen_one( x, y );
  1103.     }
  1104.  
  1105. static void
  1106. loosen_one( x, y )
  1107.     int x, y;
  1108.     {
  1109.     int i;
  1110.  
  1111.     /* Check if there's already loose sand at this location. */
  1112.     for ( i = 0; i < num_falling_sands; ++i )
  1113.     if ( falling_sands[i].active &&
  1114.          x == falling_sands[i].x && y == falling_sands[i].y )
  1115.         return;
  1116.  
  1117.     /* Check if there's room to store the new sand. */
  1118.     if ( num_falling_sands == max_falling_sands )
  1119.     {
  1120.     if ( max_falling_sands == 0 )
  1121.         {
  1122.         max_falling_sands = 20;
  1123.         falling_sands = (falling_sand*) malloc(
  1124.         (unsigned) ( max_falling_sands * sizeof(falling_sand) ) );
  1125.         }
  1126.     else
  1127.         {
  1128.         max_falling_sands *= 2;
  1129.         falling_sands = (falling_sand*) realloc(
  1130.         (char*) falling_sands,
  1131.         (unsigned) ( max_falling_sands * sizeof(falling_sand) ) );
  1132.         }
  1133.     if ( falling_sands == (falling_sand*) 0 )
  1134.         {
  1135.         (void) fprintf( stderr, "%s: out of memory\n", argv0 );
  1136.         exit( 1 );
  1137.         }
  1138.     }
  1139.  
  1140.     /* Add it. */
  1141.     falling_sands[num_falling_sands].x = x;
  1142.     falling_sands[num_falling_sands].y = y;
  1143.     falling_sands[num_falling_sands].active = 1;
  1144.     ++num_falling_sands;
  1145.     }
  1146.  
  1147. static void
  1148. drop( a )
  1149.     int a;
  1150.     {
  1151.     world[ants[a].y][ants[a].x] = E_SAND;
  1152.     invalidate( ants[a].x, ants[a].y, 1, 1 );
  1153.     loosen_one( ants[a].x, ants[a].y );
  1154.     behave( a, B_WANDERING, T_WANDERING );
  1155.     }
  1156.  
  1157. static void
  1158. behave( a, behavior, timer )
  1159.     int a, behavior, timer;
  1160.     {
  1161.     ants[a].behavior = behavior;
  1162.     ants[a].timer = 3 * timer / 4 + random() % timer / 2;
  1163.     }
  1164.  
  1165. static void
  1166. sand_fall()
  1167.     {
  1168.     int i, x, y, gotone, tipl, tipr;
  1169.  
  1170.     gotone = 0;
  1171.     for ( i = 0; i < num_falling_sands; ++i )
  1172.     if ( falling_sands[i].active )
  1173.     {
  1174.     gotone = 1;
  1175.     x = falling_sands[i].x;
  1176.     y = falling_sands[i].y;
  1177.     if ( y + 1 >= world_h )
  1178.         {
  1179.         /* Hit bottom - done falling and no compaction possible. */
  1180.         falling_sands[i].active = 0;
  1181.         continue;
  1182.         }
  1183.  
  1184.     /* Drop the sand onto the next lower sand or dirt. */
  1185.     if ( world[y + 1][x] == E_AIR )
  1186.         {
  1187.         falling_sands[i].y = y + 1;
  1188.         world[y][x] = E_AIR;
  1189.         world[falling_sands[i].y][falling_sands[i].x] = E_SAND;
  1190.         invalidate( x, y, 1, 1 );
  1191.         invalidate( falling_sands[i].x, falling_sands[i].y, 1, 1 );
  1192.         loosen_neighbors( x, y );
  1193.         continue;
  1194.         }
  1195.     
  1196.     /* Tip over an edge? */
  1197.     tipl = ( x - 1 >= 0 && world[y + 1][x - 1] == E_AIR &&
  1198.          y + 2 < world_h && world[y + 2][x - 1] == E_AIR );
  1199.     tipr = ( x + 1 < world_w && world[y + 1][x + 1] == E_AIR &&
  1200.          y + 2 < world_h && world[y + 2][x + 1] == E_AIR );
  1201.     if ( tipl || tipr )
  1202.         {
  1203.         if ( tipl && tipr )
  1204.         {
  1205.         if ( random() % 2 == 0 )
  1206.             falling_sands[i].x = x - 1;
  1207.         else
  1208.             falling_sands[i].x = x + 1;
  1209.         }
  1210.         else if ( tipl )
  1211.         falling_sands[i].x = x - 1;
  1212.         else if ( tipr )
  1213.         falling_sands[i].x = x + 1;
  1214.         falling_sands[i].y = y + 1;
  1215.         world[y][x] = E_AIR;
  1216.         world[falling_sands[i].y][falling_sands[i].x] = E_SAND;
  1217.         invalidate( x, y, 1, 1 );
  1218.         invalidate( falling_sands[i].x, falling_sands[i].y, 1, 1 );
  1219.         loosen_neighbors( x, y );
  1220.         continue;
  1221.         }
  1222.  
  1223.     /* Found the final resting place. */
  1224.     falling_sands[i].active = 0;
  1225.  
  1226.     /* Compact sand into dirt. */
  1227.     for ( i = 0; y + 1 < world_h && world[y+1][x] == E_SAND; ++y, ++i )
  1228.         ;
  1229.     if ( i >= COMPACT )
  1230.         {
  1231.         world[y][x] = E_DIRT;
  1232.         invalidate( x, y, 1, 1 );
  1233.         }
  1234.     }
  1235.     if ( ! gotone )
  1236.     num_falling_sands = 0;
  1237.     }
  1238.